
package xj.graph2d.app;

import static xj.app.BaseApplicationFrame.getResourceManager;
import static xj.app.BaseApplicationFrame.getResourceString;
import static xj.app.BaseApplicationFrame.isMacOS;
import static xj.app.BaseApplicationFrame.logInfo;
import static xj.app.BaseApplicationFrame.setAppName;
import static xj.app.BaseApplicationFrame.setReleaseDate;
import static xj.app.BaseApplicationFrame.setRevision;
import static xj.app.BaseApplicationFrame.setSplashScreenProgress;
import static xj.app.BaseApplicationFrame.setVersion;
import static xj.graph2d.DocumentConstants.XML_STENCIL_FILE_TYPE;
import static xj.graph2d.DrawShapeConstants.WRITE_XML_DEFAULT;
import static xj.graph2d.DrawShapeConstants.WRITE_XML_TEMPLATE;
import static xj.graph2d.app.Main.CENTER_PANEL;
import static xj.graph2d.app.Main.LEFT_PANEL;
import static xj.graph2d.app.Main.LOWER_PANEL;
import static xj.graph2d.app.Main.RIGHT_PANEL;
import static xj.graph2d.app.Main.UPPER_PANEL;

import java.awt.FlowLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import javax.swing.event.MenuDragMouseListener;
import javax.swing.event.MenuListener;

import org.apache.commons.codec.binary.Base64;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import xj.app.BaseApplicationFrame;
import xj.app.ClosablePanel;
import xj.app.DrawTool;
import xj.graph2d.AbstractEncoder;
import xj.graph2d.Document;
import xj.graph2d.SimpleDrawDocument;
import xj.graph2d.SimpleDrawView;
import xj.graph2d.app.DrawApp.ProjectInfo;
import xj.graph2d.app.project.ProjectType;
import xj.graph2d.app.resources.Icons;
import xj.graph2d.device.DualAnalogControlDevice;
import xj.graph2d.graph.AbstractGraphComponent;
import xj.graph2d.template.Template;
import xj.graph2d.tools.SimpleDrawTool;
import xj.meta.AbstractElement;
import xj.meta.AbstractModelElement;
import xj.util.gui.ResourceManager;
import xj.util.gui.ResizableImageIcon;
import xj.util.xml.ErrorMessageHandler;
import xj.util.xml.XMLUtil;

import org.jvnet.flamingo.common.icon.ResizableIcon;
import org.jvnet.flamingo.common.icon.ImageWrapperResizableIcon;

public class ConfigHelper { 

  public ConfigHelper(DrawApp main) { 
    this.main = main;
  }

  public static void setSystemConfigFile(String configFile) {
    systemConfigFile = configFile;
  }

  protected String getSystemProperties() { 
    Properties props = System.getProperties();
    int size = props.size();
    Iterator entries = props.entrySet().iterator();
    StringBuilder buf = new StringBuilder(); 
    while (entries.hasNext()) {
      Map.Entry entry = (Map.Entry) entries.next();
      buf.append("\t").append((String) entry.getKey()). 
	append("\t").append((String) entry.getValue()).append("\n");
    }
    return buf.toString(); 
  }


  /**
   * Processing configuration files
   */
  protected void processSystemConfig() { 
    processSystemConfig(systemConfigFile);
  }

  protected Element menubarElement;
  protected Element toolbarElement; 
  protected Element actionElement; 
  protected Element templateElement; 
  protected Element stencilElement; 

  protected void processSystemConfig(String configFile) {
    logInfo("System Properties: \n" + getSystemProperties());

    loadStyleOptions(styleOptionFile);
    logInfo("Loading SystemConfig: " + configFile);

    try {
      InputStream sysConfigIn = null;
      if (configFile != null) {
	char c = configFile.charAt(0);
	if ('/' == c) {
	  sysConfigIn = DrawApp.class.getResourceAsStream(configFile);
	} else {
	  sysConfigIn = new FileInputStream(configFile);
	}
      }
      org.w3c.dom.Document configDoc = null;
      if (sysConfigIn != null) {
	ErrorMessageHandler errorHandler = new ErrorMessageHandler(configFile);
	configDoc = XMLUtil.parseXMLDocument(sysConfigIn, errorHandler, false);
	if (errorHandler.hasErrorOrWarning()) {
	  System.err.println("Error in sys config ");
	}
      }

      if (configDoc != null) {
	Element docElement = configDoc.getDocumentElement();
	XMLUtil.stripWhiteSpace(docElement);

	if (debug) {
	  XMLUtil.indentWalk(docElement, 0);
	}

	if ("Config".equals(docElement.getLocalName()) && 
	    systemConfigNamespaceURI.equals(docElement.getNamespaceURI())) {
	  if (docElement.hasChildNodes()) {
	    NodeList nodes = docElement.getChildNodes();
	    if (nodes != null) {
	      int n = nodes.getLength();
	      for (int i = 0; i < n; i++) {

		setSplashScreenProgress(30 + 30 * i / n);

		Node node = nodes.item(i);
		if (node.getNodeType() == Node.ELEMENT_NODE) {
		  Element e = (Element) node;
		  String uri = e.getNamespaceURI();
		  if (systemConfigNamespaceURI.equals(uri)) {
		    String name = e.getLocalName();
		    if ("System".equals(name)) {
		      systemConfig(e);
		    } else if ("Layout".equals(name)) {
		      layoutConfig(e);
		    } else if ("Project".equals(name)) {
		      projectConfig(e);
		    } else if ("PlugIns".equals(name)) {
		      plugInConfig(e);
		    } else if ("ImageEncoders".equals(name)) {
		      imageEncoderConfig(e);
		    } else if ("Actions".equals(name)) {
		      actionConfig(e);
		    } else if ("Icons".equals(name)) {
		      iconConfig(e);
		    } else if ("Menubar".equals(name)) {
		      menubarConfig(e);
		    } else if ("Toolbar".equals(name)) {
		      toolbarConfig(e);
		    } else if ("Templates".equals(name)) {
		      templatesConfig(e);
		    } else if ("Stencils".equals(name)) {
		      stencilsConfig(e);
		    } else if ("Autosave".equals(name)) {
		      autoSaveConfig(e);
		    } else if ("Fonts".equals(name)) {
		      fontsConfig(e);
		    } else if ("Output".equals(name)) {
		      outputConfig(e);
		    } else if ("Input".equals(name)) {
		      inputConfig(e);
		    } else if ("InputDevices".equals(name)) {
		      inputDevicesConfig(e);
		    }
		  }
		}
	      }
	    }
	  }
	}
      }

      if (debug) {
	System.out.println("appName=" + main.getAppName());
	System.out.println("version=" + main.getVersion());
	System.out.println("revision=" + main.getRevision());
	System.out.println("releaseDate=" + main.getReleaseDate());

	System.out.println("frameWidth=" + main.getApplicationFrame().getFrameWidth());
	System.out.println("frameHeight=" + main.getApplicationFrame().getFrameHeight());
	System.out.println("canvasWidth=" + main.getCanvasWidth());
	System.out.println("canvasHeight=" + main.getCanvasHeight());
      }

      logInfo("appName=" + main.getAppName() + 
	      "; version=" + main.getVersion() + 
	      "; revision=" + main.getRevision() +
	      "; releaseDate=" + main.getReleaseDate());
      logInfo("frameWidth=" + main.getApplicationFrame().getFrameWidth() + 
	      "; frameHeight=" + main.getApplicationFrame().getFrameHeight());
      logInfo("canvasWidth=" + main.getCanvasWidth() + 
	      "; canvasHeight=" + main.getCanvasHeight());
      
    } catch (IOException e) {
      System.err.println("Error reading file " + configFile + ": " + e.getMessage());
      if (debug) {
	e.printStackTrace(System.err);
      }
    } catch (SAXParseException e) {
      // error in input
      System.err.println("Error " + configFile + ":" + e.getMessage());
      if (debug) {
	e.printStackTrace(System.err);
      }
    } catch (SAXException e) {
      // error in input
      System.err.println("Error " + configFile + ":" + e.getMessage());
      if (debug) {
	e.printStackTrace(System.err);
      }
    }

  }

  protected void systemConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("AppName".equals(name)) {
		if (main.getAppName() == null) {
		  setAppName(XMLUtil.getTextChildNodeValue(e));
		}
	      } else if ("Version".equals(name)) {
		if (main.getVersion() == null) {
		  setVersion(XMLUtil.getTextChildNodeValue(e));
		}
	      } else if ("Revision".equals(name)) {
		if (main.getRevision() == null) {
		  setRevision(XMLUtil.getTextChildNodeValue(e));
		}
	      } else if ("ReleaseDate".equals(name)) {
		if (main.getReleaseDate() == null) {
		  setReleaseDate(XMLUtil.getTextChildNodeValue(e));
		}
	      } else if ("ProjectMode".equals(name)) {
		String s = XMLUtil.getTextChildNodeValue(e);
		if (s != null) {
		  main.setProjectMode(Boolean.valueOf(s).booleanValue());
		}
	      } else if ("DocumentMode".equals(name)) {
		String s = XMLUtil.getTextChildNodeValue(e);
		main.setSingleDocumentMode("single".equals(s));
	      } else if ("Identification".equals(name)) {
		DrawApp.identification = XMLUtil.getTextChildNodeValue(e);
		DrawApp.prefix = makePrefix("visualmodeler");
		AbstractElement.setPrefix(DrawApp.prefix + "m");
		AbstractGraphComponent.setPrefix(DrawApp.prefix);
	      }
	    }
	  }
	}
      }
    }
  }

  protected String makePrefix(String seed) {
    long h = 0, l;
    if (seed != null) {
      h += seed.hashCode();
    }
    if (DrawApp.identification != null) {
      l = DrawApp.identification.hashCode();
      h += (l << 32);
    }

    String sysString = System.getProperty("os.name") + System.getProperty("os.arch") + 
      System.getProperty("os.version") + System.getProperty("java.version");
    l = sysString.hashCode();
    h += (l << 16);
    String userName = System.getProperty("user.name");
    l = userName.hashCode();
    h += (l << 8);

    h += (System.currentTimeMillis() >>> 4);

    byte[] bytes = new byte[8];
    l = h;
    for (int i = 7; i >= 0; i--) {
      bytes[i] = (byte) (l & 0xFF);
      l >>= 8;
    }

    String s = new String(Base64.encodeBase64(bytes));
    int len = s.length();
    String prefix = s.substring(1, len - 2);

    // System.out.println("DrawApp.makePrefix(): prefix=" + prefix );

    return prefix;
  }

  protected void projectConfig(Element root) {
    if (root != null) {
      String projname = root.getAttribute("name");
      String type = root.getAttribute("type");
      ProjectType projtype = ProjectType.toProjectType(type);
      String itemname = null;
      Document.DocumentType itemtype = null;
      if (root.hasChildNodes()) {
	NodeList nodes = root.getChildNodes();
	if (nodes != null) {
	  int n = nodes.getLength();
	  for (int i = 0; i < n; i++) {
	    Node node = nodes.item(i);
	    if (node.getNodeType() == Node.ELEMENT_NODE) {
	      Element e = (Element) node;
	      String uri = e.getNamespaceURI();
	      if (systemConfigNamespaceURI.equals(uri)) {
		String name = e.getLocalName();
		if ("Item".equals(name)) {
		  itemname = e.getAttribute("name");
		  type = e.getAttribute("type");
		  break;
		}
	      }
	    }
	  }
	}
      }

      itemtype = Document.toDocumentType(type);
      initProjInfo = new ProjectInfo();
      initProjInfo.projName = projname;
      initProjInfo.projType = projtype;
      initProjInfo.itemName = itemname;
      initProjInfo.itemType = itemtype;
      main.initProjectManager(initProjInfo);
    }
  }

  protected void layoutConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("FrameDimension".equals(name)) {
		try {
		  String s = e.getAttribute("width");
		  BaseApplicationFrame frame = main.getApplicationFrame();
		  if (frame != null) { 
		    frame.setFrameWidth(Integer.parseInt(s));
		  }
		} catch (NumberFormatException ex) {
		}
		try {
		  String s = e.getAttribute("height");
		  BaseApplicationFrame frame = main.getApplicationFrame();
		  if (frame != null) { 
		    frame.setFrameHeight(Integer.parseInt(s));
		  }
		} catch (NumberFormatException ex) {
		}
	      } else if ("CanvasDimension".equals(name)) {
		try {
		  String s = e.getAttribute("width");
		  main.canvasWidth = Integer.parseInt(s);
		} catch (NumberFormatException ex) {
		}
		try {
		  String s = e.getAttribute("height");
		  main.canvasHeight = Integer.parseInt(s);
		} catch (NumberFormatException ex) {
		}
	      } else if ("Zoom".equals(name)) {
		String s = e.getAttribute("slider");
		main.useZoomSlider = Boolean.valueOf(s).booleanValue();
	      } else if ("ViewOptions".equals(name)) {
		main.showViewOptions = true; 
	      } else if ("Panels".equals(name)) {
		try {
		  String s = e.getAttribute("divider");
		  main.dividerSize = Integer.parseInt(s);
		} catch (NumberFormatException ex) {
		}
		String titled = e.getAttribute("titled");
		main.titledPanels = Boolean.valueOf(titled).booleanValue();
		String shadow = e.getAttribute("shadow");
		main.shadowPanels = Boolean.valueOf(shadow).booleanValue();
	
		NodeList pnodes = e.getChildNodes();
		if (pnodes != null) {
		  int pn = pnodes.getLength();
		  for (int p = 0; p < pn; p++) {
		    Node pnode = pnodes.item(p);
		    if (pnode.getNodeType() == Node.ELEMENT_NODE) {
		      Element pe = (Element) pnode;
		      String puri = pe.getNamespaceURI();
		      if (systemConfigNamespaceURI.equals(puri)) {
			String pname = pe.getLocalName();
			if ("LeftPanel".equals(pname)) {
			  panelConfig(pe, LEFT_PANEL);
			} else if ("RightPanel".equals(pname)) {
			  panelConfig(pe, RIGHT_PANEL);
			} else if ("CenterPanel".equals(pname)) {
			  panelConfig(pe, CENTER_PANEL);
			}
		      }
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void panelConfig(Element root, int pos) {
    if (root != null && 
	pos >= 0 && pos <= 2) {
      int width = main.panelWidth[pos];
      try {
	String s = root.getAttribute("width");
	width = Integer.parseInt(s);
	main.panelWidth[pos] = width;
      } catch (NumberFormatException ex) {
      }

      if (root.hasChildNodes()) {
	NodeList nodes = root.getChildNodes();
	if (nodes != null) {
	  int n = nodes.getLength();
	  for (int i = 0; i < n; i++) {
	    Node node = nodes.item(i);
	    if (node.getNodeType() == Node.ELEMENT_NODE) {
	      Element e = (Element) node;
	      String uri = e.getNamespaceURI();
	      if (systemConfigNamespaceURI.equals(uri)) {
		String ename = e.getLocalName();
		String name = null;
		int height = 0;
		int vpos = UPPER_PANEL;
		if ("TopPanel".equals(ename)) {

		  // System.out.println("navPanelConfig(): " +
		  // (pos) + " TopPanel");
		  height = main.upperPanelHeight[pos];
		  try {
		    String s = e.getAttribute("height");
		    height = Integer.parseInt(s);
		    main.upperPanelHeight[pos] = height;
		  } catch (NumberFormatException ex) {
		  }
		  name = e.getAttribute("name");
		  vpos = UPPER_PANEL;
		} else if ("BottomPanel".equals(ename)) {
		  // System.out.println("navPanelConfig(): " +
		  // (pos) + "BottomPanel");
		  int fheight = 600;
		  BaseApplicationFrame frame = main.getApplicationFrame();
		  if (frame != null) { 
		    fheight = frame.getFrameHeight();
		  }
		  try {
		    String s = e.getAttribute("height");
		    if (s != null && s.length() > 0) { 
		      height = Integer.parseInt(s);
		      main.upperPanelHeight[pos] = (fheight - height);
		    } else { 
		      height = fheight -  main.upperPanelHeight[pos];
		    }
		  } catch (NumberFormatException ex) {
		  }
		  name = e.getAttribute("name");
		  vpos = LOWER_PANEL;
		}

		if (name != null) {
		  String str = e.getAttribute("visible");
		  boolean visible = "true".equals(str);
		  if (visible) {
		    if (pos != CENTER_PANEL || vpos != UPPER_PANEL) {
		      //main.setPanelName(name, vpos, pos);
		      ClosablePanel panel = new ClosablePanel(name);
		      str = e.getAttribute("closable");
		      boolean closable = "true".equals(str);
		      str = e.getAttribute("closed");
		      boolean closed = "true".equals(str);
		      str = e.getAttribute("detachable");
		      boolean detachable = "true".equals(str);
		      str = e.getAttribute("detached");
		      boolean detached = "true".equals(str);
		      panel.setPosition(vpos, pos); 
		      panel.setClosable(closable);
		      panel.setClosed(closed);
		      panel.setDetachable(detachable);
		      panel.setDetached(detached);

		      String icon = e.getAttribute("icon");
		      if (icon != null && 
			  icon.length() > 0) {
			Icon ic = DrawApp.icons.get(icon);
			if (ic != null) {
			  panel.setIcon(ic);
			}
		      }		      

		      int dwidth = width; 
		      int dheight = height; 
		      try {
			String s = e.getAttribute("dwidth");
			dwidth = Integer.parseInt(s);
		      } catch (NumberFormatException ex) {
		      }
		      try {
			String s = e.getAttribute("dheight");
			dheight = Integer.parseInt(s);
		      } catch (NumberFormatException ex) {
		      }
		      panel.setWidth(width);
		      panel.setHeight(height);
		      panel.setDetachedWidth(dwidth);
		      panel.setDetachedHeight(dheight);

		      main.addClosablePanel(panel);
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void plugInConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("PlugIn".equals(name)) {
		String plugInName = e.getAttribute("name");
		String plugInClassName = e.getAttribute("class");
		if (plugInName != null && 
		    plugInClassName != null) {
		  plugInName = plugInName.trim();
		  plugInClassName = plugInClassName.trim();

		  try {
		    Class plugInClass = Class.forName(plugInClassName);
		    Object obj = plugInClass.newInstance();
		    if (obj instanceof PlugIn) {
		      PlugIn plugIn = (PlugIn) obj;
		      plugIn.initPlugIn(main);
		      main.addPlugIn(name, plugIn);

		      if (debug) {
			System.out.println("Instantiate PlugIn: name=" + plugInName + 
					   " class=" + plugInClassName);
		      }
		      
		      logInfo("Instantiate plug-in: name=" + plugInName);
		    }
		  } catch (ClassNotFoundException ex) {
		    System.err.println("Unable to load class " + plugInClassName);
		    System.err.println(ex.getMessage());
		    if (debug) {
		      ex.printStackTrace();
		    }
		  } catch (InstantiationException ex) {
		    System.err.println("Unable to instantiate class " + plugInClassName);
		    System.err.println(ex.getMessage());
		  } catch (IllegalAccessException ex) {
		    System.err.println("Unable to instantiate class " + plugInClassName);
		    System.err.println(ex.getMessage());
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void imageEncoderConfig(Element root) {
    if (root != null && 
	root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("Encoder".equals(name)) {
		String encoderName = e.getAttribute("name");
		String encoderExtension = e.getAttribute("ext");
		String encoderClassName = e.getAttribute("class");
		if (encoderName != null && 
		    encoderExtension != null && 
		    encoderClassName != null) {
		  encoderName = encoderName.trim();
		  encoderExtension = encoderExtension.trim();
		  encoderClassName = encoderClassName.trim();

		  try {
		    Class encoderClass = Class.forName(encoderClassName);
		    Object obj = encoderClass.newInstance();
		    if (obj instanceof AbstractEncoder) {
		      AbstractEncoder encoder = (AbstractEncoder) obj;
		      encoder.setName(encoderName);
		      encoder.setFileType(encoderExtension, 
					  getResourceString(encoderName + ".des"));
		      encoder.setImageType(encoderExtension);
		      main.addEncoder(encoder);

		      if (debug) {
			System.out.println("Instantiate encoder: name=" + encoderName + 
					   " class=" + encoderClassName);
		      }

		      logInfo("Instantiate image encoder: name=" + encoderName);
		    }
		  } catch (ClassNotFoundException ex) {
		    System.err.println("Unable to load class " + encoderClassName);
		    System.err.println(ex.getMessage());
		    if (debug) {
		      ex.printStackTrace();
		    }
		  } catch (InstantiationException ex) {
		    System.err.println("Unable to instantiate class " + encoderClassName);
		    System.err.println(ex.getMessage());
		  } catch (IllegalAccessException ex) {
		    System.err.println("Unable to instantiate class " + encoderClassName);
		    System.err.println(ex.getMessage());
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void iconConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      String dir = root.getAttribute("dir");
      NodeList nodes = root.getChildNodes();
      if (dir != null) {
	dir = dir.trim();
	int l = dir.length();
	if (l > 0) {
	  char c = dir.charAt(l - 1);
	  if (c != '/') {
	    dir += "/";
	  }
	} else {
	  dir = null;
	}
      }
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("IconSet".equals(name)) {
		String iconSetName = e.getAttribute("name");
		if ("ShapeIcon".equals(iconSetName)) {
		  Icons.loadIcons(DrawApp.icons); 
		}
	      } else if ("Icon".equals(name)) {
		String iconName = e.getAttribute("name");
		String iconRes = e.getAttribute("res");
		String iconClassName = e.getAttribute("class");
		// String file = e.getAttribute("file");
		if (iconName != null) {
		  iconName = iconName.trim();
		  if (DrawApp.icons.containsKey(iconName)) {
		    System.err.println("Duplicate icon name: " + iconName + 
				       ". The previous one is overriden.");
		  }

		  if (iconRes != null && iconRes.length() > 0) {
		    iconRes = iconRes.trim();
		    if (dir != null) {
		      iconRes = dir + iconRes;
		    }
		    try {
		      URL iconURL = DrawApp.class.getResource(iconRes);
		      Icon icon = new ResizableImageIcon(iconURL);
		      //Icon icon = ImageWrapperResizableIcon.getIcon(iconURL, new Dimension(16, 16)) ;
		      DrawApp.icons.put(iconName, icon);

		      if (debug) {
			System.out.println("Load icon: name=" + iconName + 
					   " res=" + iconRes);
		      }
		    } catch (Exception ex) {
		      System.err.println("Unable to load icon: " + iconRes);
		      System.err.println(ex.getMessage());
		    }
		  } else if (iconClassName != null && 
			     iconClassName.length() > 0) {
		    iconClassName = iconClassName.trim();
		    try {
		      Class iconClass = Class.forName(iconClassName);
		      Object obj = iconClass.newInstance();
		      if (obj instanceof Icon) {
			Icon icon = (Icon) obj;
			DrawApp.icons.put(iconName, icon);

			if (debug) {
			  System.out.println("Instantiate icon: name=" + iconName + 
					     " class=" + iconClassName);
			}
		      }
		    } catch (ClassNotFoundException ex) {
		      System.err.println("Unable to load class " + iconClassName);
		      System.err.println(ex.getMessage());
		      if (debug) {
			ex.printStackTrace();
		      }
		    } catch (InstantiationException ex) {
		      System.err.println("Unable to instantiate class " + iconClassName);
		      System.err.println(ex.getMessage());
		    } catch (IllegalAccessException ex) {
		      System.err.println("Unable to instantiate class " + iconClassName);
		      System.err.println(ex.getMessage());
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void actionConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("Action".equals(name)) {
		String actionName = e.getAttribute("name");
		String actionClassName = e.getAttribute("class");
		if (actionName != null && actionClassName != null) {
		  actionName = actionName.trim();
		  actionClassName = actionClassName.trim();

		  if (DrawApp.actions.containsKey(actionName)) {
		    System.err.println("Duplicate action name: " + actionName + 
				       ". The previous one is overriden.");
		  }
		  try {
		    Class actionClass = Class.forName(actionClassName);
		    Object obj = actionClass.newInstance();
		    if (obj instanceof DrawAction) {
		      DrawAction action = (DrawAction) obj;
		      action.setMain(main);
		      DrawApp.actions.put(actionName, action);

		      if (debug) {
			System.out.println("Instantiate action: name=" + actionName + 
					   " class=" + actionClassName);
		      }
		      logInfo("Instantiate action: name=" + actionName);
		    }
		  } catch (ClassNotFoundException ex) {
		    System.err.println("Unable to load class " + actionClassName);
		    System.err.println(ex.getMessage());
		    if (debug) {
		      ex.printStackTrace();
		    }
		  } catch (InstantiationException ex) {
		    System.err.println("Unable to instantiate class " + actionClassName);
		    System.err.println(ex.getMessage());
		  } catch (IllegalAccessException ex) {
		    System.err.println("Unable to instantiate class " + actionClassName);
		    System.err.println(ex.getMessage());
		  } catch (Exception ex) {
		    System.err.println("Unable to instantiate class " + actionClassName);
		    System.err.println(ex.getMessage());
		    ex.printStackTrace(System.err);
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void menubarConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      main.menuBar = new JMenuBar();
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("Menu".equals(name)) {
		JMenu menu = makeMenu(e);
		if (menu != null) {
		  main.menuBar.add(menu);
		}
	      } else if ("HorizontalGlue".equals(name)) {
		main.menuBar.add(Box.createHorizontalGlue());
	      } else if ("Group".equals(name)) {
		groupConfig(e);
	      }
	    }
	  }
	}
      }
      //main.setJMenuBar(main.menuBar);
    }
  }

  protected void toolbarConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      String toolbarName = root.getAttribute("name");
      String typeStr = root.getAttribute("type");
      boolean single = false; 
      if  ("single".equals(typeStr)) {
	single = true; 
      }
      if (toolbarName != null && 
	  toolbarName.length() > 0) {
	// JToolBar toolbar = new JToolBar();
	JPanel panel = null;
	JToolBar toolbar;
	if (single) {
	  toolbar = new JToolBar();
	  toolbar.setFloatable(false);
	  toolbar.setRollover(true);
	  toolbar.setFocusable(false);
	} else {
	  panel = new JPanel();
	  panel.setLayout(new FlowLayout(FlowLayout.LEFT));
	  toolbar = new JToolBar();
	  toolbar.setFloatable(false);
	  toolbar.setRollover(true);
	  toolbar.setFocusable(false);
	}
	// toolbar.setBackground(UIManager.getColor("window"));

	NodeList nodes = root.getChildNodes();
	if (nodes != null) {
	  int n = nodes.getLength();
	  for (int i = 0; i < n; i++) {
	    Node node = nodes.item(i);
	    if (node.getNodeType() == Node.ELEMENT_NODE) {
	      Element e = (Element) node;
	      String uri = e.getNamespaceURI();
	      if (systemConfigNamespaceURI.equals(uri)) {
		String name = e.getLocalName();
		JComponent tool = null;
		if ("ToolButton".equals(name)) {
		  tool = makeToolButton(e);
		  if (tool != null) {
		    toolbar.add(tool);
		  }

		  /*
		  String actionButton = e.getAttribute("actionButton");
		  if (Boolean.valueOf(actionButton)) { 
		    tool = makeActionToolButton(e);
		  } else { 
		    tool = makeToolButton(e);
		  }
		} else if ("ToolStrip".equals(name)) {
		  JComponent strip = makeToolStrip(e);
		  if (strip != null) {
		    toolbar.add(strip);
		  }
		  */
		} else if ("Separator".equals(name)) {
		  if (single) { 
		    toolbar.add(new JToolBar.Separator());
		  } else { 
		    panel.add(toolbar); 
		    toolbar = new JToolBar();
		    toolbar.setFloatable(false);
		    toolbar.setRollover(true);
		    toolbar.setFocusable(false);
		  }
		} else if ("Group".equals(name)) {
		  groupConfig(e);
		}
	      }
	    }
	  }
	}

	if (main.toolbars.containsKey(toolbarName)) {
	  System.err.println("Duplicate toolbar name: " + toolbarName + 
			     ". The previous one is overriden.");
	}
	if (single) { 
	  main.toolbars.put(toolbarName, toolbar);
	} else { 
	  main.toolbars.put(toolbarName, panel);
	}
      }
    }
  }

  protected void groupConfig(Element root) {
    if (root != null) {
      String name = root.getAttribute("name");
      if (name != null && name.length() > 0) {
	if (main.groups.containsKey(name)) {
	  System.err.println("Duplicate group name: " + name + 
			     ". The previous one is overriden.");
	}
	ButtonGroup group = new ButtonGroup();
	main.groups.put(name, group);
      }
    }
  }

  protected void templatesConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      AbstractModelElement.setInitMode(true);

      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String ename = e.getLocalName();
	      if ("Template".equals(ename)) {
		String tempName = e.getAttribute("name");
		String tempDisplay = e.getAttribute("display");
		String tempFile = e.getAttribute("file");
		String tempClass = e.getAttribute("class");
		String action = e.getAttribute("action");
		String style = e.getAttribute("style");
		String group = e.getAttribute("group");
		String graph = e.getAttribute("graph");

		if (debug) {
		  System.out.println("Instantiate template: name=" + tempName + 
				     " display=" + tempDisplay + " file=" + tempFile + 
				     " class=" + tempClass + " action=" + action + 
				     " group=" + group);
		}

		logInfo("Loading template: name=" + tempName + 
			" display=" + tempDisplay);

		ActionListener actionListener = null;
		if (action != null && action.length() > 0) {
		  Object act = DrawApp.actions.get(action);
		  if (act instanceof ActionListener) {
		    actionListener = (ActionListener) act;
		  }
		}
		ButtonGroup g = null;
		if (group != null && group.length() > 0) {
		  Object o = main.groups.get(group);
		  if (o instanceof ButtonGroup) {
		    g = (ButtonGroup) o;
		  }
		}

		if (tempName != null) {
		  ToolPanel toolPanel = null;
		  if (tempFile != null && tempFile.length() > 0) {
		    ResourceManager resourceManager = getResourceManager();
		    toolPanel = ToolPanel.loadTemplate(tempName, tempDisplay,
						       systemConfigPrefix + tempFile, actionListener, g,
						       Boolean.valueOf(graph).booleanValue(), main,
						       resourceManager, DrawApp.icons);
		  } else if (tempClass != null && tempClass.length() > 0) {
		    try {
		      Class templateClass = Class.forName(tempClass);
		      Object obj = templateClass.newInstance();
		      if (obj instanceof Template) {
			Template template = (Template) obj;
			template.setName(tempName);
			int tempStyle = Template.allTemplateStyle; 
			if ("all".equals(style)) {
			  tempStyle = Template.allTemplateStyle;
			} else if ("default".equals(style)) {
			  tempStyle = Template.classicTemplateStyle;
			}
			template.setTemplateStyle(tempStyle);
			template.setStyleOptions(styleOptions);
			if (Boolean.valueOf(graph).booleanValue()) {
			  template.setGraphComponent(true);
			}
			template.makeTemplate(DrawApp.icons);
			template.addDefaultStereotypes();
			template.initTools();
			main.templates.put(tempName, template);
			ResourceManager resourceManager = getResourceManager();
			toolPanel = ToolPanel.loadTemplate(tempName,
							   tempDisplay, template, 
							   actionListener, g, main,
							   resourceManager, DrawApp.icons);
		      }
		    } catch (ClassNotFoundException ex) {
		      System.err.println("Unable to load class " + tempClass);
		      System.err.println(ex.getMessage());
		      if (debug) {
			ex.printStackTrace();
		      }
		    } catch (InstantiationException ex) {
		      System.err.println("Unable to instantiate class " + tempClass);
		      System.err.println(ex.getMessage());
		    } catch (IllegalAccessException ex) {
		      System.err.println("Unable to instantiate class " + tempClass);
		      System.err.println(ex.getMessage());
		    }
		  }

		  if (toolPanel != null) {
		    main.templatePanels.add(toolPanel);
		  }
		}
	      }
	    }
	  }
	}
      }

      AbstractModelElement.setInitMode(false);
    }
  }

  protected void stencilsConfig(Element root) {
    AbstractModelElement.setInitMode(true);
    
    String userhome = System.getProperty("user.home");
    String appDir = main.getAppDir();
    String stencilDir = userhome + File.separator + appDir + 
      File.separator + DrawApp.STENCIL_DIR;
    File dir = new File(stencilDir); 
    if (dir.isDirectory()) {
      //System.out.println("Loading stencils in " + dir); 
      logInfo("Loading stencils in " + dir); 

      //List dirs = new ArrayList(); 
      //List javas = new ArrayList(); 
      File files[] = dir.listFiles(); 
      if (files != null) {
	int n = files.length;
	for (int i = 0; i < n; i++) {
	  if (files[i] != null) { 
	    if (!files[i].isDirectory()) { 
	      String filename = files[i].getName();
	      if (filename.endsWith("." + DrawApp.stencilFileExtension)) { 
		//System.out.println("Loading file " + filename); 
		logInfo("Loading stencil file " + filename); 

		String name = filename.substring(0, filename.length() - 4);
		
		SimpleDrawView mainView = main.view;
		SimpleDrawDocument mainDoc = main.doc;
		try { 
		  main.initDocView(); 
		  SimpleDrawView view = main.view;
		  SimpleDrawDocument doc = main.doc;
		  doc.openFile(files[i].getAbsolutePath(), XML_STENCIL_FILE_TYPE); 
		  DrawApp.fitCanvas(view, StencilPanel.MINIMUM_WIDTH, StencilPanel.MINIMUM_HEIGHT);
		  main.stencils.put(name, main.view); 
		  view.setStencilMode(true);
		  view.setShowRuler(false);
		  view.setShowMargin(false);
		  view.setScaleFactor(0.5f);
		} catch (IOException ex) { 
		  ex.printStackTrace();
		} catch (xj.graph2d.DocumentException ex) { 
		  ex.printStackTrace();
		} finally { 
		  main.doc = mainDoc;
		  main.view = mainView;
		}
	      }
	    }
	  }
	}
      }
    }

    AbstractModelElement.setInitMode(false);
  }

  protected void outputConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("XML".equals(name)) {
		XMLOutputConfig(e);
	      }
	    }
	  }
	}
      }
    }
  }

  protected void XMLOutputConfig(Element root) {
    if (root != null) {
      String s = root.getAttribute("mode");
      if ("template".equals(s)) {
	main.doc.setWriteXMLMode(WRITE_XML_TEMPLATE);
      } else {
	main.doc.setWriteXMLMode(WRITE_XML_DEFAULT);
      }

      if (root.hasChildNodes()) {
	NodeList nodes = root.getChildNodes();
	if (nodes != null) {
	  int n = nodes.getLength();
	  for (int i = 0; i < n; i++) {
	    Node node = nodes.item(i);
	    if (node.getNodeType() == Node.ELEMENT_NODE) {
	      Element e = (Element) node;
	      String uri = e.getNamespaceURI();
	      if (systemConfigNamespaceURI.equals(uri)) {
		String name = e.getLocalName();
		if ("Namespace".equals(name)) {
		  String nsuri = e.getAttribute("uri");
		  String nsprefix = e.getAttribute("prefix");
		  main.getApplicationFrame().setNamespace(nsuri, nsprefix);
		  main.doc.setNamespace(nsuri, nsprefix);
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void inputConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("XML".equals(name)) {
		XMLInputConfig(e);
	      }
	    }
	  }
	}
      }
    }
  }

  protected void XMLInputConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("Namespace".equals(name)) {
		String nsstrict = e.getAttribute("strict");
		main.doc.setStrictNamespace(Boolean.valueOf(nsstrict).booleanValue());
	      }
	    }
	  }
	}
      }
    }
  }

  protected void inputDevicesConfig(Element root) {
    if (root != null && root.hasChildNodes()) {
      NodeList nodes = root.getChildNodes();
      if (nodes != null) {
	int n = nodes.getLength();
	for (int i = 0; i < n; i++) {
	  Node node = nodes.item(i);
	  if (node.getNodeType() == Node.ELEMENT_NODE) {
	    Element e = (Element) node;
	    String uri = e.getNamespaceURI();
	    if (systemConfigNamespaceURI.equals(uri)) {
	      String name = e.getLocalName();
	      if ("Controller".equals(name)) {
		String devName = e.getAttribute("name");
		String devType = e.getAttribute("type");
		if ("Dual-Analog-Control".equals(devType)) {
		  main.devices.add(new DualAnalogControlDevice(devName));
		}
	      }
	    }
	  }
	}
      }
    }
  }

  protected void fontsConfig(Element root) {
    if (root != null) {
      String stdOnly = root.getAttribute("standardOnly");
      main.useStandardFontsOnly = Boolean.valueOf(stdOnly).booleanValue();
    }
  }

  protected void autoSaveConfig(Element root) {
    if (root != null) {
      String interval = root.getAttribute("interval");
      try { 
	int v = Integer.parseInt(interval); 
	main.setAutoSaveInterval(v);
      } catch (NumberFormatException ex) {}
    }
  }

  protected JMenu makeMenu(Element m) {
    JMenu menu = null;
    String name = m.getAttribute("name");
    String icon = m.getAttribute("icon");
    String mnemonic = m.getAttribute("mnemonic");
    String menuAction = m.getAttribute("menuAction");
    String enabled = m.getAttribute("enabled");

    if (debug) {
      System.out.println("makeMenu(): name=" + name + " icon=" + icon
	                 + " mnemonic=" + mnemonic + " menuAction="
	                 + (menuAction == null ? "null" : menuAction));
    }

    boolean menuEnabled = true;
    if ("false".equals(enabled)) {
      menuEnabled = false;
    }

    String label = getResourceString(name + ".text");
    menu = new JMenu(label);
    menu.setActionCommand(name);
    menu.setEnabled(menuEnabled);

    if (!isMacOS() && 
	mnemonic != null && 
	mnemonic.length() > 0) {
      char c = mnemonic.charAt(0);
      if (c != '\u0000') {
	menu.setMnemonic(c);
      }
    }
    if (icon != null && 
	icon.length() > 0) {
      Icon ic = DrawApp.icons.get(icon);
      if (ic != null) {
	menu.setIcon((Icon) ic);
      }
    }
    if (menuAction != null && 
	menuAction.length() > 0) {
      Object act = DrawApp.actions.get(menuAction);
      if (act instanceof MenuListener) {
	menu.addMenuListener((MenuListener) act);
	if (act instanceof DrawAction) {
	  ((DrawAction) act).setSource(menu);
	}
      }
    }

    main.menus.put(name, menu);

    NodeList nodes = m.getChildNodes();
    if (nodes != null) {
      int n = nodes.getLength();
      for (int i = 0; i < n; i++) {
	Node node = nodes.item(i);
	if (node.getNodeType() == Node.ELEMENT_NODE) {
	  Element e = (Element) node;
	  String uri = e.getNamespaceURI();
	  if (systemConfigNamespaceURI.equals(uri)) {
	    String sname = e.getLocalName();
	    if ("MenuItem".equals(sname)) {
	      JMenuItem mi = makeMenuItem(e);
	      if (mi != null) {
		menu.add(mi);
	      }
	    } else if ("Menu".equals(sname)) {
	      JMenu submenu = makeMenu(e);
	      if (submenu != null) {
		menu.add(submenu);
	      }
	    } else if ("Separator".equals(sname)) {
	      menu.add(new JSeparator());
	    }
	  }
	}
      }
    }

    return menu;
  }

  protected JMenuItem makeMenuItem(Element mi) {
    JMenuItem menuitem = null;
    String name = mi.getAttribute("name");
    String icon = mi.getAttribute("icon");
    String type = mi.getAttribute("type");
    String mnemonic = mi.getAttribute("mnemonic");
    String accel = mi.getAttribute("accel");
    String mask = mi.getAttribute("mask"); // shift alt
    String selected = mi.getAttribute("selected");
    String enabled = mi.getAttribute("enabled");
    String group = mi.getAttribute("group");
    String action = mi.getAttribute("action");
    String dragAction = mi.getAttribute("dragAction");

    if (debug) {
      System.out.println("makeMenuItem(): name=" + name + 
			 " icon=" + icon + " type=" + type + 
			 " mnemonic=" + mnemonic + " accel=" + accel + 
			 " mask=" + mask + "\n\tselected=" + selected + 
			 " enabled=" + enabled + " group=" + group + 
			 " action=" + action + " dragAction=" + dragAction);
    }

    boolean menuSelected = ("true".equals(selected));
    boolean menuEnabled = true;
    if ("false".equals(enabled)) {
      menuEnabled = false;
    }

    if (type != null) {
      if ("CheckBox".equals(type)) {
	menuitem = new JCheckBoxMenuItem();
	menuitem.setSelected(menuSelected);
      } else if ("RadioButton".equals(type)) {
	menuitem = new JRadioButtonMenuItem();
	menuitem.setSelected(menuSelected);
      }
    }
    if (menuitem == null) {
      menuitem = new JMenuItem();
    }
    menuitem.setEnabled(menuEnabled);

    String label = getResourceString(name + ".text");
    if (label != null) { 
      menuitem.setText(label);
    } else { 
      menuitem.setText(name);
    }
    menuitem.setActionCommand(name);

    if (icon != null && 
	icon.length() > 0) {
      Object ic = DrawApp.icons.get(icon);
      if (ic instanceof Icon) {
	menuitem.setIcon((Icon) ic);
      }
    }

    if (!isMacOS() && 
	mnemonic != null && 
	mnemonic.length() > 0) {
      char c = mnemonic.charAt(0);
      if (c != '\u0000') {
	menuitem.setMnemonic(c);
      }
    }

    if (accel != null && accel.length() > 0) {
      int keycode = 0;
      boolean isFunctionKey = false;
      if (accel.length() == 1) {
	char c = accel.charAt(0);
	if (!Character.isISOControl(c)) {
	  if (Character.isLowerCase(c)) {
	    keycode = Character.toUpperCase(c);
	  } else {
	    keycode = c;
	  }
	}
      } else {
	accel = accel.toLowerCase();
	if (accel.indexOf("up") != -1) {
	  keycode = KeyEvent.VK_UP;
	} else if (accel.indexOf("down") != -1) {
	  keycode = KeyEvent.VK_DOWN;
	} else if (accel.indexOf("left") != -1) {
	  keycode = KeyEvent.VK_LEFT;
	} else if (accel.indexOf("right") != -1) {
	  keycode = KeyEvent.VK_RIGHT;
	} else if (accel.indexOf("home") != -1) {
	  keycode = KeyEvent.VK_HOME;
	} else if (accel.indexOf("end") != -1) {
	  keycode = KeyEvent.VK_END;
	} else if (accel.indexOf("page-up") != -1) {
	  keycode = KeyEvent.VK_PAGE_UP;
	} else if (accel.indexOf("page-down") != -1) {
	  keycode = KeyEvent.VK_PAGE_DOWN;
	} else if (accel.indexOf("insert") != -1) {
	  keycode = KeyEvent.VK_INSERT;
	} else if (accel.indexOf("delete") != -1) {
	  keycode = KeyEvent.VK_DELETE;
	} else if (accel.indexOf("enter") != -1) {
	  keycode = KeyEvent.VK_ENTER;
	} else if (accel.indexOf("esc") != -1) {
	  keycode = KeyEvent.VK_ESCAPE;
	} else if (accel.indexOf("plus") != -1) {
	  keycode = KeyEvent.VK_PLUS;
	} else if (accel.indexOf("minus") != -1) {
	  keycode = KeyEvent.VK_MINUS;
	} else if (accel.indexOf("f12") != -1) {
	  keycode = KeyEvent.VK_F12;
	  isFunctionKey = true;
	} else if (accel.indexOf("f11") != -1) {
	  keycode = KeyEvent.VK_F11;
	  isFunctionKey = true;
	} else if (accel.indexOf("f10") != -1) {
	  keycode = KeyEvent.VK_F10;
	  isFunctionKey = true;
	} else if (accel.indexOf("f9") != -1) {
	  keycode = KeyEvent.VK_F9;
	  isFunctionKey = true;
	} else if (accel.indexOf("f8") != -1) {
	  keycode = KeyEvent.VK_F8;
	  isFunctionKey = true;
	} else if (accel.indexOf("f7") != -1) {
	  keycode = KeyEvent.VK_F7;
	  isFunctionKey = true;
	} else if (accel.indexOf("f6") != -1) {
	  keycode = KeyEvent.VK_F6;
	  isFunctionKey = true;
	} else if (accel.indexOf("f5") != -1) {
	  keycode = KeyEvent.VK_F5;
	  isFunctionKey = true;
	} else if (accel.indexOf("f4") != -1) {
	  keycode = KeyEvent.VK_F4;
	  isFunctionKey = true;
	} else if (accel.indexOf("f3") != -1) {
	  keycode = KeyEvent.VK_F3;
	  isFunctionKey = true;
	} else if (accel.indexOf("f2") != -1) {
	  keycode = KeyEvent.VK_F2;
	  isFunctionKey = true;
	} else if (accel.indexOf("f1") != -1) {
	  keycode = KeyEvent.VK_F1;
	  isFunctionKey = true;
	}
      }

      if (keycode != 0) {
	if (isFunctionKey) {
	  menuitem.setAccelerator(KeyStroke.getKeyStroke(keycode, 0));
	} else {
	  int accelMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
	  if (mask != null) {
	    mask = mask.toLowerCase();
	    if (mask.indexOf("shift") != -1) {
	      accelMask |= InputEvent.SHIFT_MASK;
	    }
	    if (mask.indexOf("alt") != -1) {
	      accelMask |= InputEvent.ALT_MASK;
	    }
	  }
	  menuitem.setAccelerator(KeyStroke.getKeyStroke(keycode, accelMask));
	}
      }
    }

    if (group != null && group.length() > 0) {
      Object o = main.groups.get(group);
      if (o instanceof ButtonGroup) {
	ButtonGroup g = (ButtonGroup) o;
	g.add(menuitem);
      }
    }

    if (action != null && action.length() > 0) {
      Object act = DrawApp.actions.get(action);
      if (act instanceof ActionListener) {
	menuitem.addActionListener((ActionListener) act);
	if (act instanceof DrawAction) {
	  ((DrawAction) act).setSource(menuitem);
	}
      }
    }
    if (dragAction != null && dragAction.length() > 0) {
      Object act = DrawApp.actions.get(dragAction);
      if (act instanceof MenuDragMouseListener) {
	menuitem.addMenuDragMouseListener((MenuDragMouseListener) act);
	if (act instanceof DrawAction) {
	  ((DrawAction) act).setSource(menuitem);
	}
      }
    }

    main.menus.put(name, menuitem);

    return menuitem;
  }


  protected JComponent makeToolButton(Element tb) {
    AbstractButton tool = null;
    String command = tb.getAttribute("command");
    String icon = tb.getAttribute("icon");
    String toggle = tb.getAttribute("toggle");
    String selected = tb.getAttribute("selected");
    String enabled = tb.getAttribute("enabled");
    String group = tb.getAttribute("group");
    String action = tb.getAttribute("action");
    String changeAction = tb.getAttribute("changeAction");

    if (debug) {
      System.out.println("makeToolButton(): command=" + command + 
			 " icon=" + icon + " selected=" + selected + 
			 " enabled=" + enabled + "\n\tgroup=" + group + 
			 " action=" + action + " changeAction=" + changeAction);
    }

    if (icon != null && icon.length() > 0) {
      Icon ic = DrawApp.icons.get(icon);
      if ("false".equals(toggle)) {
	tool = new JButton(ic);
      } else {
	tool = new JToggleButton(ic);
      }
    }
    if (tool == null) {
      if ("false".equals(toggle)) {
	tool = new JButton(command);
      } else {
	tool = new JToggleButton(command);
      }
    }
    tool.setActionCommand(command);

    boolean toolSelected = ("true".equals(selected));
    tool.setSelected(toolSelected);
    boolean toolEnabled = true;
    if ("false".equals(enabled)) {
      toolEnabled = false;
    }
    tool.setEnabled(toolEnabled);

    String tip = getResourceString(command + ".tip");
    if (tip != null) {
      tip = "<html><center>" + tip.replaceAll("\n", "<br/>") + "</center></html>";
      tool.setToolTipText(tip);
    }

    if (group != null && 
	group.length() > 0) {
      Object o = main.groups.get(group);
      if (o instanceof ButtonGroup) {
	ButtonGroup g = (ButtonGroup) o;
	g.add(tool);
      }
    }

    if (action != null && 
	action.length() > 0) {
      Object act = DrawApp.actions.get(action);
      if (act instanceof ActionListener) {
	tool.addActionListener((ActionListener) act);
	if (act instanceof DrawAction) {
	  ((DrawAction) act).setSource(tool);
	}
      }
    }
    if (changeAction != null && changeAction.length() > 0) {
      Object act = DrawApp.actions.get(changeAction);
      if (act instanceof ChangeListener) {
	tool.addChangeListener((ChangeListener) act);
	if (act instanceof DrawAction) {
	  ((DrawAction) act).setSource(tool);
	}
      }
    }

    DrawTool t = main.view.getTool(command);
    if (t instanceof SimpleDrawTool) {
      SimpleDrawTool st = (SimpleDrawTool) t;
      st.setToolButton(tool);
    }
    return tool;
  }

  protected void loadStyleOptions(String styleOptionFile) {
    if (styleOptionFile != null) {
      try {
	InputStream styleIn = DrawApp.class.getResourceAsStream(styleOptionFile);
	if (styleIn != null) {
	  styleOptions.load(styleIn);
	  if (debug) {
	    System.out.println("DrawApp: style option: " + styleOptions);
	  }
	} else {
	  if (debug) {
	    System.out.println("DrawApp: styleIn==null");
	  }
	}
      } catch (IOException e) {
	System.out.println("DrawApp: style option file not found: " + styleOptionFile);
      }
    }
  }

  protected DrawApp main;

  protected ProjectInfo initProjInfo = null;

  protected Properties styleOptions = new Properties();

  protected static String systemConfigFile = "/config/draw/VisualModelerConfig.xml";

  protected static String systemConfigPrefix = "/config/draw/";

  protected static String systemConfigNamespaceURI = "http://www.aesthsoft.com/VisualModeler/Config";

  protected static String styleOptionFile = "/config/draw/VisualModelerStyle.properties";

  public static final boolean debug = false;

}
